package com.zlsy.thread.objectandthreadcommonsuse.producterandconsumer;

import java.util.Date;
import java.util.LinkedList;

/**
 * @author zhouliang
 * @date 2020/03/05
 **/
public class ProducerConsumerModelByWaitAndNotify {

/*
    private static final EventStorage eventStorage = new EventStorage();
*/

    public static void main(String[] args) {
        EventStorage eventStorage = new EventStorage();
        Producer producer = new Producer(eventStorage);
        Consumer consumer = new Consumer(eventStorage);
        Thread thread = new Thread(producer);
        Thread thread1 = new Thread(consumer);
        thread.start();
        thread1.start();
    }

}

class Producer implements Runnable {

    private EventStorage eventStorage;

    Producer(EventStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            eventStorage.put();
        }
    }
}

class Consumer implements Runnable {

    private EventStorage eventStorage;

    Consumer(EventStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            eventStorage.take();
        }
    }
}

class EventStorage {
    private int maxSize;
    private LinkedList<Date> list;

    public EventStorage() {
        this.maxSize = 10;
        this.list = new LinkedList<>();
    }

    /**
     * 从仓库取数据
     */
    public synchronized void take() {

        //如果多个线程同时被唤醒，那么都需要再次检查是否满足被唤醒的条件，因为其中一个线程被唤醒后继续执行，
        // 另外的线程这个时候就需要重新进入等待状态，如果用while就可以实现，但是if无法实现。

        //仓库空了，需要等待放进来，才能取
        while (list.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("我消费了数据" + list.poll() + ",目前仓库剩下:" + list.size());
        //每次消费完都通知生产者继续生产
        notify();
    }

    /**
     * 把数据放到仓库
     */
    public synchronized void put() {
        //如果仓库是满的，我们就等待消费者消费了再放
        while (list.size() == 10) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(new Date());
        System.out.println("我生产了一条数据,目前仓库已经有数据:" + list.size());
        //生产完数据通知消费者消费
        notify();
    }

}